#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from define import DEFSTOCK
from define import INIT_AMOUNT
from define import TRADER_LOW
from define import TRADER_HIGH
from define import TRADE_STATE_S
from define import TRADE_STATE_W
from define import TRADE_STATE_F
from define import HOST
from define import PORT
from define import MAX_CLIENT

from stock import Stock
from stock import StockPool
from trade import TradeRequest
from tradermanager import TraderManager

import multiprocessing.synchronize
from multiprocessing import Process
import os
import socket
import time
import logging
from threading import Thread
from threading import Event
import random
import unittest
import errno
import sys

class StockExchange(object):
    class ServerThread(Thread):
        def __init__(self):
            Thread.__init__(self)
            self.name = 'Server Thread'
            self.stopped = True
            self.workers = []
            self.stock_pool = StockPool()       # How to share this variable???

            self.log = logging.getLogger("StockExchange")
            self.log.warning("STOCKEXCHANGE: %s" % ("Server thread created."))

        def run(self):
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            try:
                sock.bind((HOST, PORT))
                sock.listen(MAX_CLIENT)
                self.log.warning("STOCKEXCHANGE: We're listening on port %d" % (PORT))
            except socket.error, e:
                self.log.warning("STOCKEXCHANGE: ServerThread: Socket error: %s" % (PORT))
                return

            self.stopped = False
            while not self.stopped:
                try:
                    conn, addr = sock.accept()
                except socket.error, e:
                    continue
                self.log.warning("STOCKEXCHANGE: ServerThread: Connected by %s" % addr[0])
                t = StockExchange.RequestHandlerThread(conn, addr,
                                                       self.stock_pool)
                t.start()
                self.workers.append(t)

            # If we're here, it mean we should exit, so clean up.
            self.log.warning("STOCKEXCHANGE: We're stopping")
            self.server_thread.stop()
            try:
                self.sock.shutdown(socket.SHUT_RDWR)
                self.sock.close()
            except:
                pass

            for t in self.workers:
                t.stop()
                #t.join()

        def stop(self):
            self.stop = True

        def destroy(self):
            # release all resources here
            pass

    class RequestHandlerThread(Thread):
        def __init__(self, conn=None, addr=None, pool=None):
            Thread.__init__(self)
            self.name = 'Server Thread'
            self.stopped = True

            self.conn = conn
            self.addr = addr
            self.stock_pool = pool

            self.log = logging.getLogger("StockExchange")
            self.log.warning("STOCKEXCHANGE: RequestHandlerThread: Request handler thread created.")

        def run(self):
            self.stopped = False
            while not self.stopped:
                try:
                    data = self.conn.recv(100)
                except socket.error, e:
                    self.log.critical('STOCKEXCHANGE: Socket recv Error: %s' % e)
                    break
                if not data: 
                    self.log.warning('STOCKEXCHANGE: Handle Request: EMPTY REQUEST!!!')
                    #conn.shutdown(socket.SHUT_RDWR)
                    break
                self.log.warning('STOCKEXCHANGE: Handle Request: "%s"' % data)
                try:
                    trade_request = TradeRequest(data.split(": ")[1].split('-')[:4]) 
                except IndexError, e:
                    self.log.warning('STOCKEXCHANGE: Malformed Request. Ignored!')
                    continue
                res = self.stock_pool.trade(trade_request)
                self.log.warning('STOCKEXCHANGE: Send Response: "%s"' % res)
                self.conn.send(res)

        def stop(self):
            self.stopped = True

    def __init__(self):
        object.__init__(self)
        self.log = logging.getLogger("TH1")
        self.log.warning("STOCKEXCHANGE: %s" % ("Stock Exchange created."))

        self.name = 'Stock Exchange'
        self.trader_manager = TraderManager(self)

        self.stock_pool = StockPool()

    def __str__(self):
        return self.name

    def accept_request(self, req):
        ''' Accepct trade requests from Trader Manager, and pass them on to Stock
        Pool.
        '''
        res = self.stock_pool.trade(req)

    def run(self):
        # Create socket server
        time.sleep(20)
        # Should do some clean work before exit!!!
        self.trader_manager.stop()

    def stop(self):
        self.log.warning("STOCKEXCHANGE: We're stopping")
        self.server_thread.stop()

def main():
    FORMAT = "%(asctime)-15s %(message)s"
    logging.basicConfig(format=FORMAT)
    log = logging.getLogger("STOCKEXCHANGE")
    log.warning("STOCKEXCHANGE: Start StockExchange")

    se = StockExchange()
    se.run()
    sys.exit(1)

if __name__ == '__main__':
    main()

